package com.deviceplug;

import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static android.content.Context.USB_SERVICE;


public class UstorageDeviceInstance {

    private static UstorageDeviceInstance instance;
    private static Lock mLock= new ReentrantLock();
    public static final String ACTION_USB_PERMISSION = "wfd.action.USB_PERMISSION";
    private UsbManager mUsbManager;
    private CUSBListener mUSBListener;
    private Context g_cotext_;

    private ArrayList<CameraControlTransfer> curDevListArray;
    public ArrayList<CameraControlTransfer> devListArray;

    /** 设备发现回掉 */
    private IUsbDevicePlugDelegate iUsbDevicePlugDelegate;

    public static UstorageDeviceInstance getInstance() {
        if (instance == null) {
            mLock.lock();
            if (instance == null) {
                instance = new UstorageDeviceInstance();
            }
            mLock.unlock();
        }
        return instance;
    }

    UstorageDeviceInstance() {
        devListArray = new ArrayList<CameraControlTransfer>();
        curDevListArray = new ArrayList<CameraControlTransfer>();
    }


     final String getUSBFSName(final CUSBListener.UsbControlBlock ctrlBlock) {
        String result = null;
        final String name = ctrlBlock.getDeviceName();
        final String[] v = !TextUtils.isEmpty(name) ? name.split("/") : null;
        if ((v != null) && (v.length > 2)) {
            final StringBuilder sb = new StringBuilder(v[0]);
            for (int i = 1; i < v.length - 2; i++)
                sb.append("/").append(v[i]);
            result = sb.toString();
        }
        if (TextUtils.isEmpty(result)) {
            result = "/dev/bus/usb";
        }
        return result;
    }

    /**
     * 尝试是否有连接设备（OTG）
     */
    public void tryAttcheDeviceHandle(Context context, IUsbDevicePlugDelegate iUsbDevicePlugDelegate) {
        this.iUsbDevicePlugDelegate = iUsbDevicePlugDelegate;
        mUsbManager = (UsbManager) context.getSystemService(USB_SERVICE);

        devListArray.clear();
        curDevListArray.clear();

        g_cotext_ = context;
//        //拿到OTG设备列表
        HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
        Log.d("deviceList", String.valueOf(deviceList.size()));
        for (UsbDevice usbDevice : deviceList.values()) {
            Log.i("Start",  String.valueOf(usbDevice.getProductName()));
            Boolean find = false;
            for (int i = 0; i < curDevListArray.size(); i++) {
                if(usbDevice.equals(curDevListArray.get(i))){
                    find= true;
                    Log.e("ERROR", "find device");
                    Log.e("ERROR",  String.valueOf(usbDevice.getDeviceClass()));
                    Log.e("ERROR",  String.valueOf(usbDevice.getDeviceName()));
                    Log.e("ERROR",  String.valueOf(usbDevice.getProductName()));
                    continue;
                }
            }
            if(usbDevice.getDeviceClass() != 0xEF) {
                Log.e("ERROR", "getDeviceClass!=0xEF");
                Log.e("ERROR",  String.valueOf(usbDevice.getDeviceClass()));
                Log.e("ERROR",  String.valueOf(usbDevice.getDeviceName()));
                Log.e("ERROR",  String.valueOf(usbDevice.getProductName()));
               continue;
            }
            if(!find){
//                if(usbDevice.getVendorId() != 0x0581 || usbDevice.getProductId() != 0x0b20){
//                    continue;
//                }

                Log.d("usbDevice", String.valueOf(usbDevice.toString()));
                Log.d("getDeviceSubclass", String.valueOf(usbDevice.getDeviceSubclass()));
                Log.d("devName", usbDevice.getDeviceName());
                Log.d("proName", usbDevice.getProductName());
                Log.d("vid", String.valueOf(usbDevice.getVendorId()));
                Log.d("pid", String.valueOf(usbDevice.getProductId()));
                CameraControlTransfer infos = new CameraControlTransfer();
                infos.dev = usbDevice;
                infos.bPermission = false;
                try {
                    infos.usbListener = mUSBListener;
                    mUSBListener = new CUSBListener(context, mOnDeviceConnectListener);
                    mUSBListener.register();
                    mUSBListener.requestPermission(usbDevice);
                }catch (Exception e) {
                    e.printStackTrace();
                }
                curDevListArray.add(infos);
            }
        }
    }

    public boolean startAcceptLicense(int position, Context context, Object deviceInfo) {
        if(devListArray.get(position).usbListener.hasPermission((UsbDevice)deviceInfo)){
            return true;
        }
        try {
            devListArray.get(position).usbListener.requestPermission((UsbDevice) deviceInfo);
            mUsbManager.openDevice((UsbDevice) deviceInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    //<<<--------------------------------------- Usb 相关处理--------------------------------------------
    /**
     * 获取符合信息的OTG设备
     * @param usbManager
     */
    private UsbDevice acceptOTGDeviceInfo(Context context, UsbManager usbManager) {
        UsbDevice device = null;

        //拿到OTG设备列表
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();

        for (UsbDevice usbDevice : deviceList.values()) {
            int vendorId = usbDevice.getVendorId();
            if (vendorId == 0x0c45) {
                device = usbDevice;
                break;
            }
        }
        return device;
    }

    private void acceptLicense(Context context, Object deviceInfo) {
        try {
            mUSBListener = new CUSBListener(context, mOnDeviceConnectListener);

            mUSBListener.register();

            UsbDevice usbDevice = (UsbDevice) deviceInfo;

            // request permission [frank.chang 7/25/2018]
            mUSBListener.requestPermission((UsbDevice)usbDevice);

            // open the device [frank.chang 7/25/2018]
            mUsbManager.openDevice((UsbDevice)usbDevice);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    // implement OnDeviceConnectListener
    private final CUSBListener.OnDeviceConnectListener mOnDeviceConnectListener = new CUSBListener.OnDeviceConnectListener() {
        @Override
        public void onAttach(final UsbDevice device) {
            iUsbDevicePlugDelegate.usbDeviceInsert();
        }

        @Override
        public void onConnect(final UsbDevice device, final CUSBListener.UsbControlBlock ctrlBlock, final boolean createNew) {
            for (int i = 0; i < curDevListArray.size(); i++) {
                if(device.equals(curDevListArray.get(i).dev)){
                    Log.d("onConnect", device.toString());
                    CameraControlTransfer cct = curDevListArray.get(i);
                    cct.bPermission = true;
                    cct.connection = ctrlBlock.mConnection;
                    String fsName = new String();
                    fsName = ctrlBlock.getDeviceName();;
                    cct.usbFSName = fsName;
                    cct.fd = ctrlBlock.getFileDescriptor();
                    mUsbManager.openDevice(device);
                    devListArray.add(cct);
                    break;
                }
            }
            iUsbDevicePlugDelegate.permissionFinish(true, ctrlBlock);
        }

        @Override
        public void onDisconnect(final UsbDevice device, final CUSBListener.UsbControlBlock ctrlBlock) {

        }

        @Override
        public void onDettach(final UsbDevice device) {
            for (int i = 0; i < devListArray.size(); i++) {
                if(device.equals(device)){
                    devListArray.remove(i);
                    break;
                }
            }
            iUsbDevicePlugDelegate.usbDeviceDetached();
        }

        @Override
        public void onCancel() {

        }
    };

}